#include "EditorEventHandler.hpp"
#include "EditorManager.hpp"
#include "GameState.h"

EditorEventHandler::EditorEventHandler()
{
	m_MouseButtonDown = false;
	m_FromPath = false;

}

// Things called every frame, not just when events occur
void EditorEventHandler::Update()
{
	// Update mouse position
	int x, y;
	SDL_GetMouseState(&x, &y);
	m_ScreenMouse.x = x;
	m_ScreenMouse.y = y;
	m_GameMouse.x = x + m_pEditorManager->m_pClipPlane->GetX();
	m_GameMouse.y = y + m_pEditorManager->m_pClipPlane->GetY();

	// Handle scrolling and room movement
	HandleScrolling();
	HandleRoomMovement(m_Event);
}

void EditorEventHandler::HandleEvents(SDL_Event* event)
{
	// Get new keystate data
	m_Keystates = SDL_GetKeyState(NULL);
	m_Event = event;

	// only update the selection box if we are actually rendering it
	if(m_pEditorManager->m_DrawSelectionBox)
		HandleSelectionBox(event);

	HandleInput(event);
	HandleGUI(event);
	HandleRoomSelection(event);
	//HandleRoomMovement(event);
}

void EditorEventHandler::HandleSelectionBox(SDL_Event* event)
{
	// only update if we are not in a panel
	if(!GUI->GetPanelBounds(m_ScreenMouse.x, m_ScreenMouse.y))
		m_pEditorManager->m_pSelectionBoxHandler->HandleEvents(m_Keystates, m_GameMouse, event);
	//else
	//	m_pEditorManager->m_pSelectionBoxHandler->ResetSelectionMouse();
}

void EditorEventHandler::HandleRoomMovement(SDL_Event* event)
{
	if(event->button.type == SDL_MOUSEBUTTONDOWN)
		m_MouseButtonDown = true;
	if(event->button.type == SDL_MOUSEBUTTONUP)
	{
		m_MouseButtonDown = false;
		if(m_pEditorManager->m_EnableRoomMovement)
		{
			if(!GUI->GetPanelBounds(m_ScreenMouse.x, m_ScreenMouse.y))
			{
				m_HandleMouseButtonUpRoomMovementEvent = true;
				m_pEditorManager->m_MergePathListsInRoomManager = false;
			}

			if(m_pEditorManager->m_pRoomA != NULL)
			{
				m_pEditorManager->m_pMinimap->Remove(*m_pEditorManager->m_pRoomA);
				m_pEditorManager->m_pMinimap->Load(*m_pEditorManager->m_pRoomA);
			}
		}
	}

	// we have to keep looping until we have handled all of the room's paths and regenerated them all. 
	if(m_HandleMouseButtonUpRoomMovementEvent)
	{
		// Get another path
		BasePath path = m_pEditorManager->m_pRoomManager->GetPath(m_MovementRoomID);

		// If the room has no more paths, then we can stop regenerating paths.  We have to remerge the paths in the room manager, also.
		if(path.roomID == -1 || path.ID_a == -1 || path.ID_b == -1)
		{
			m_HandleMouseButtonUpRoomMovementEvent = false;
			m_pEditorManager->m_MergePathListsInRoomManager = true;
			m_pEditorManager->m_pRoomManager->MergePathLists();
		}
		else
		{
			// Remove the path from the manager and from the minimap
			m_pEditorManager->m_pMinimap->Remove(*MapGen->GetRoom(path.roomID));
			m_pEditorManager->m_pRoomManager->RemoveRoom(*MapGen->GetRoom(path.roomID));

			// Setup everything so we can create a new path
			m_pEditorManager->m_pRoomA = MapGen->GetRoom(path.ID_a);
			m_pEditorManager->m_pRoomB = MapGen->GetRoom(path.ID_b);
			m_pEditorManager->m_PathRiver = path.river;
			m_pEditorManager->m_PathWidth = path.width;
			m_pEditorManager->m_ActiveImgID = path.imgID;
			m_pEditorManager->m_SmoothPath = path.smoothingPercentage;
			m_pEditorManager->m_CreatePath = true;	
		}
	}

	// if we are  not in the GUI and the mouse button is down and the left mouse button is down and room A is not null and we are not drawing the selection box and room movement is enabled
	if(!GUI->GetPanelBounds(m_ScreenMouse.x, m_ScreenMouse.y) && m_MouseButtonDown && event->button.button == SDL_BUTTON_LEFT && m_pEditorManager->m_pRoomA != NULL && !m_pEditorManager->m_DrawSelectionBox && m_pEditorManager->m_EnableRoomMovement)
	{
		// ID of the room we are moving
		m_MovementRoomID = m_pEditorManager->m_pRoomA->ID;

		// we also want to be in the room
		if(InRoom(m_GameMouse, *m_pEditorManager->m_pRoomA))
		{
			m_pEditorManager->m_pRoomA->x1 = (m_GameMouse.x / TILE_DIMENSIONS) - (m_pEditorManager->m_pRoomA->w / 2.0);
			m_pEditorManager->m_pRoomA->x2 = m_pEditorManager->m_pRoomA->x1 + m_pEditorManager->m_pRoomA->w;
			m_pEditorManager->m_pRoomA->y1 = m_GameMouse.y / TILE_DIMENSIONS - (m_pEditorManager->m_pRoomA->h / 2.0);
			m_pEditorManager->m_pRoomA->y2 = m_pEditorManager->m_pRoomA->y1 + m_pEditorManager->m_pRoomA->h;

			MapGen->ChangeRoom(*m_pEditorManager->m_pRoomA);
		}
	}

}
void EditorEventHandler::HandleScrolling()
{
	// if we are not in the GUI and we are not moving a selection box
	if(!GUI->GetPanelBounds(m_ScreenMouse.x, m_ScreenMouse.y) && !m_Keystates[SDLK_q] && !m_Keystates[SDLK_w] && !m_Keystates[SDLK_a] && !m_Keystates[SDLK_s])
		m_pEditorManager->m_pCamera->Update(m_ScreenMouse, m_Keystates);
}

void EditorEventHandler::HandleGUI(SDL_Event* event)
{
	if(event->type == SDL_MOUSEBUTTONDOWN)
	{
		// Algorithms
		{
			// Register the panel and get the button ID we are hovering over (if we are hoving over one)
			GUI->RegisterPanel(Key->GetPanelIDs()->Editor_Algorithms);
			int ID = GUI->GetActivePanelButtonID(m_ScreenMouse);
					
			if(ID != -1)
			{
				if(m_AlgorithmDelay.GetElapsedMilliseconds() > 400)
				{
					m_pEditorManager->m_ActiveAlgorithm = ID;
					GUI->SetButtonShading(false);
					GUI->SetButtonShading(true, ID);
					GUI->DeactivePanel();
					GUI->RegisterPanel(Key->GetPanelIDs()->Editor_Tiles);
					GUI->ActivatePanel();
					m_AlgorithmDelay.Restart();
				}
			}
		}

		// Image ids
		{
			GUI->RegisterPanel(Key->GetPanelIDs()->Editor_Tiles);
			int ID = GUI->GetActivePanelButtonID(m_ScreenMouse);
					
			if(ID != -1)
			{
				if(m_AlgorithmDelay.GetElapsedMilliseconds() > 400)
				{
					m_pEditorManager->m_ActiveImgID = ID;
					GUI->SetButtonShading(false);
					GUI->SetButtonShading(true, ID);
					if(!m_FromPath)
						m_pEditorManager->m_CreateRoom = true;
					else
						m_pEditorManager->m_CreatePath = true;

					GUI->DeactivePanel();
					m_AlgorithmDelay.Restart();
				}
			}
		}

		// Buttons
		//Editor_Buttons, Editor_buttonID_displaySelection, Editor_buttonID_buildRoom, , ,
		{
			GUI->RegisterPanel(Key->GetPanelIDs()->Editor_Buttons);
			
			int ID = GUI->GetButtonID(m_ScreenMouse.x, m_ScreenMouse.y);
			//GUI->SetButtonShading(false);
			//GUI->SetButtonShading(true, ID);
			
			// only run if the mouse is up
			if(event->type == SDL_MOUSEBUTTONDOWN)
			{
				if(ID == Key->GetPanelIDs()->Editor_buttonID_displaySelection)
				{
					m_pEditorManager->m_DrawSelectionBox = !m_pEditorManager->m_DrawSelectionBox;
					m_pEditorManager->m_EnableRoomMovement = false;
				}
				
				if(ID == Key->GetPanelIDs()->Editor_buttonID_buildRoom)
				{
					if(m_pEditorManager->m_DrawSelectionBox == true)
					{
						GUI->RegisterPanel(Key->GetPanelIDs()->Editor_Algorithms);
						GUI->ActivatePanel();
						m_FromPath = false;
					}
				}

				if(ID == Key->GetPanelIDs()->Editor_buttonID_buildPath)
				{
					// if both rooms are not null and we are not drawing the selection box
					if(m_pEditorManager->m_pRoomA != NULL && m_pEditorManager->m_pRoomB != NULL)
						if(m_pEditorManager->m_DrawSelectionBox == false)
						{
							GUI->RegisterPanel(Key->GetPanelIDs()->Editor_Tiles);
							GUI->ActivatePanel();
							m_FromPath = true;
						}
				}

				if(ID == Key->GetPanelIDs()->Editor_buttonID_moveRooms)
				{
					m_pEditorManager->m_DrawSelectionBox = false;
					m_pEditorManager->m_EnableRoomMovement = !m_pEditorManager->m_EnableRoomMovement;
					//m_pEditorManager->m_pRoomA = NULL;
					m_pEditorManager->m_pRoomB = NULL;
				}

				// remove a room
				if(ID == Key->GetPanelIDs()->Editor_buttonID_removeRoom)
					m_pEditorManager->m_RemoveRoom = true;

				if(ID == Key->GetPanelIDs()->Editor_buttonID_saveToLua)
					m_pEditorManager->m_pRoomManager->ExportToLua("test.lua");
			}
		}
	}

}

// This function handles room selection
void EditorEventHandler::HandleRoomSelection(SDL_Event* event)
{
	if(!m_pEditorManager->m_DrawSelectionBox)
	{
		m_pEditorManager->m_pMouseOverRoom = NULL;
		vector<Room*> rooms = m_pEditorManager->m_pRoomManager->GetRoomsOnscreen(m_pEditorManager->m_pClipPlane);
		for(unsigned int i = m_pEditorManager->m_RoomSelectionStart; i < rooms.size(); ++i) // skip the background
			if(InRoom(m_pEditorManager->m_pEditorEvents->GetGameMouse(), *rooms[i]))
			{
				if(m_pEditorManager->m_pRoomA != rooms[i] && m_pEditorManager->m_pRoomB != rooms[i])
					m_pEditorManager->m_pMouseOverRoom = rooms[i];
				//DrawPrimitives->DrawRectangle(rooms[i]->x1 * TILE_DIMENSIONS - m_pClipPlane->GetX(), rooms[i]->y1 * TILE_DIMENSIONS - m_pClipPlane->GetY(),
				//	rooms[i]->x2 * TILE_DIMENSIONS - m_pClipPlane->GetX(), rooms[i]->y2 * TILE_DIMENSIONS - m_pClipPlane->GetY(), gray, .5);

				// if we are hitting shift, ctrl, mouse button right / left over a room, and we are not in the GUI, then select it
				if(!GUI->GetPanelBounds(GetScreenMouse().x, GetScreenMouse().y))
				{
					if((GetKeystates()[SDLK_LSHIFT] || (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT)) && m_pEditorManager->m_pRoomB != rooms[i])	
					{
						m_pEditorManager->m_pRoomA = rooms[i];
					}
					if((GetKeystates()[SDLK_LCTRL] || (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_RIGHT)) && m_pEditorManager->m_pRoomA != rooms[i])
					{
						m_pEditorManager->m_pRoomB = rooms[i];
					}
				}
			}
	}
}
void EditorEventHandler::HandleInput(SDL_Event *event)
{

	switch(event->type)
	{
		// SDL KEY DOWN EVENTS =========================================
		case SDL_KEYDOWN:
		{
			switch(event->key.keysym.sym)
			{
				// P key, path
				case SDLK_p:
				{
					GUI->RegisterPanel(Key->GetPanelIDs()->Editor_Tiles);
					GUI->ActivatePanel();
					m_FromPath = true;
					break;
				}


				// B key, room
				case SDLK_b:
				{
					GUI->RegisterPanel(Key->GetPanelIDs()->Editor_Algorithms);
					GUI->ActivatePanel();
					m_FromPath = false;
					break;
				}

				// R key
				// switch the draw selection box if r is pressed
				case SDLK_r:
				{
					m_pEditorManager->m_DrawSelectionBox = !m_pEditorManager->m_DrawSelectionBox;
					break;
				}

				// K key
				// remove a room if k is pressed
				case SDLK_k:
				{
					m_pEditorManager->m_RemoveRoom = true;
					break;
				}

				// L key
				// Save the file to lua if 'L' is pressed
				case SDLK_l:
				{
					m_pEditorManager->m_pRoomManager->ExportToLua("test.lua");
					break;
				}

			}
		}

		break;
		// ==============================================================

	

	}




	if(m_Keystates[SDLK_PAGEUP])
		if(m_pEditorManager->m_RoomSelectionStart < m_pEditorManager->m_pRoomManager->GetRooms()->size())
			m_pEditorManager->m_RoomSelectionStart++;

	if(m_Keystates[SDLK_PAGEDOWN])
		if(m_pEditorManager->m_RoomSelectionStart > 0)
			m_pEditorManager->m_RoomSelectionStart--;

	//If the user has Xed out the window
    if( event->type == SDL_QUIT )
        set_next_state( STATE_EXIT );
        
	
	// scrolling up / down, if we are drawing a selection box, modify density, otherwise modify path width or path smoothing
	if(event->button.button == SDL_BUTTON_WHEELUP && event->type == SDL_MOUSEBUTTONDOWN)
		if(m_pEditorManager->m_DrawSelectionBox)
		{
			if(m_pEditorManager->m_Density < 1.0)
				m_pEditorManager->m_Density += .01;
		}
		else
		{
			if(m_Keystates[SDLK_LCTRL])
			{
				if(m_pEditorManager->m_PathWidth < 20)
					m_pEditorManager->m_PathWidth += 1;
			}
			else
				if(m_pEditorManager->m_SmoothPath < 2)
					m_pEditorManager->m_SmoothPath += .02;
		}

	if(event->button.button == SDL_BUTTON_WHEELDOWN && event->type == SDL_MOUSEBUTTONDOWN)
		if(m_pEditorManager->m_DrawSelectionBox)
		{
			if(m_pEditorManager->m_Density > .01)
				m_pEditorManager->m_Density -= .01;
		}
		else
		{
			if(m_Keystates[SDLK_LCTRL])
			{
				if(m_pEditorManager->m_PathWidth > 1)
					m_pEditorManager->m_PathWidth -= 1;
			}
			else
				if(m_pEditorManager->m_SmoothPath > -.1)
					m_pEditorManager->m_SmoothPath -= .02;
		}

	// if we are not drawing a selection box and middle mouse button is pressed down then reverse the river
	if(!m_pEditorManager->m_DrawSelectionBox && event->button.button == SDL_BUTTON_MIDDLE && event->type == SDL_MOUSEBUTTONDOWN)
		m_pEditorManager->m_PathRiver = !m_pEditorManager->m_PathRiver;
}